package com.tyut.musicdreamer.framework.starter.storage.task;

import com.tyut.musicdreamer.framework.starter.storage.model.StorageClass;
import com.tyut.musicdreamer.framework.starter.storage.service.StorageService;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 存储类别更新任务基类
 * 提供通用的存储类别更新逻辑，子类可以扩展此类以实现特定业务场景的存储类别更新
 */
@Slf4j
@RequiredArgsConstructor
public abstract class BaseStorageClassUpdateTask {

    @Getter
    protected final StorageService storageService;
    
    // 对象访问计数器
    protected final Map<String, Long> accessCounter = new ConcurrentHashMap<>();
    
    /**
     * 记录文件访问
     * @param objectKey 对象键
     */
    public void recordAccess(String objectKey) {
        accessCounter.compute(objectKey, (key, count) -> count == null ? 1 : count + 1);
    }
    
    /**
     * 执行存储类别更新
     * 由子类实现具体的业务逻辑
     */
    public abstract void updateStorageClass();
    
    /**
     * 根据访问次数确定存储类别
     * @param accessCount 访问次数
     * @return 适合的存储类别
     */
    protected StorageClass determineStorageClass(long accessCount) {
        if (accessCount > 10000) {
            // 热门文件，使用标准存储
            return StorageClass.STANDARD;
        } else if (accessCount > 1000) {
            // 适中访问，使用低频存储
            return StorageClass.IA;
        } else if (accessCount > 100) {
            // 低频访问，使用归档存储
            return StorageClass.ARCHIVE;
        } else {
            // 极少访问，使用冷归档存储
            return StorageClass.COLD_ARCHIVE;
        }
    }
    
    /**
     * 执行存储类别更新
     * @param objectKey 对象键
     * @param targetClass 目标存储类别
     * @return 是否更新成功
     */
    protected boolean updateObjectStorageClass(String objectKey, StorageClass targetClass) {
        try {
            log.info("正在更新对象[{}]的存储类别为[{}]", objectKey, targetClass);
            return storageService.updateStorageClass(objectKey, targetClass);
        } catch (Exception e) {
            log.error("更新对象[{}]存储类别失败", objectKey, e);
            return false;
        }
    }
} 